﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using SimpleServiceBus.Endpoints.ActiveMQ.Configuration;
using SimpleServiceBus.Endpoint;
using SimpleServiceBus.Endpoints.ActiveMQ.Transport;
using Sample.Messages;

namespace SampleConsumer {
    public partial class Form1: Form, IPictureService {
        private IMessagingEndpoint fEndpoint;

        public Form1() {
            InitializeComponent();
            Logger.TextLogged += Logger_TextLogged;
        }

        private void Form1_FormClosing(object sender, FormClosingEventArgs e) {
            if(fEndpoint != null) {
                fEndpoint.Stop();
                fEndpoint = null;
            }
        }

        private void Form1_FormClosed(object sender, FormClosedEventArgs e) {
            Logger.TextLogged -= Logger_TextLogged;
        }

        private void Logger_TextLogged(string message) {
            if(this.InvokeRequired) {
                Action<String> _callback = Logger_TextLogged;
                this.Invoke(_callback, message);
            }
            else {
                if(txtLog.Text != null && txtLog.Text.Length > 128 * 1024)
                    txtLog.Text = "";
                txtLog.Text += String.Format("[{0:HH:mm:ss}] {1}{2}", DateTime.Now, message, Environment.NewLine);
                txtLog.SelectionStart = txtLog.Text.Length;
                txtLog.SelectionLength = 0;
                txtLog.ScrollToCaret();
            }
        }

        private ActiveMQConfigurator CreateConfigurator() {
            return new ActiveMQConfigurator("ActiveMQ.SampleConsumer", "Samples.Consumer")
                .ConnectTo(txtBrokerUrl.Text)
                //.FormatMessagesUsing(MessageFormat.Binary) // Text is the default format
                .SetupDefaultConsumerPool(x => {
                    x.WorkerCount = 5;
                    x.ConsumeQueue("Samples.Simple");
                    // Note that eventhough you're subscribing within a pool of 5 workers, we will use only one thread to subscribe to the topics,
                    // otherwise any published topic would be duplicated 5 times!
                    x.Subscribe(typeof(Area1));
                    //x.Subscribe(typeof(Area1), "XPATH '//anyType[contains(MainValue, \"Foo\")]'");    // supposed to work but cannot get xpath to work at all. Maybe a configuration issue in ActiveMQ...
                    //x.Subscribe(typeof(Area1), "XPATH '/anyType/MainValue = \"Foo\"'");    // supposed to work but cannot get xpath to work at all. Maybe a configuration issue in ActiveMQ...
                    x.Subscribe(typeof(Area2));
                    x.Subscribe("Other.>");
                    x.Subscribe("Samples.HardcodedArea3", null, false, "MyDurableName");

                })
                .SetupConsumerPool("PingPong", x => {
                    x.WorkerCount = 1;
                    x.ConsumeQueue("Samples.Ping");
                })
                .SetupMessageHandlers(x => {
                   x.Register(this.GetType().Assembly);
                })
                .SetupMessageTypes(x => {
                    x.Register(typeof(Area4)); // this is required because we have no handler for type Area4, and thus Area4 is not auto-registered.
                                               // there is however a handler on the base class (OtherTopic) which can then consume any subclass.
                                               // see OtherHandler.
                })
                .SetupLocalServices(x => {
                    x.Register<IPictureService>(this); // this service will be used by the PictureHandler
                })
                .SetupMessageDestinations(x => {
                    x.Send(typeof(PingPong), "Samples.Pong");
                    x.Send(typeof(SquareResponse), "Samples.Producer");
                });
        }

        private IMessagingEndpoint CreateEndpoint() {
            var _configurator = CreateConfigurator();
            var _result = _configurator.CreateEndpoint();
            _result.EndpointOnline += Handle_EndpointOnline;
            _result.EndpointOffline += Handle_EndpointOffline;
            _result.MessageBus.MessageProcessingException += new EventHandler<SimpleServiceBus.Bus.MessageProcessingErrorEventArgs>(MessageBus_MessageProcessingException);
            return _result;
        }

        private void MessageBus_MessageProcessingException(object sender, SimpleServiceBus.Bus.MessageProcessingErrorEventArgs e) {
            Logger.Log("An exception occurred while processing a message: {0}", e.Exception.Message);
            if(e.Exception.InnerException != null)
                Logger.Log(e.Exception.InnerException.Message);
        }

        private void Handle_EndpointOnline(object sender, EndpointEventArgs e) {
            Logger.Log("Endpoint online");
        }

        private void Handle_EndpointOffline(object sender, EndpointEventArgs e) {
            Logger.Log("Endpoint offline");
        }

        private void btnStart_Click(object sender, EventArgs e) {
            fEndpoint = CreateEndpoint();
            fEndpoint.Start();
            btnStart.Enabled = false;
            btnStop.Enabled = true;
        }

        private void btnStop_Click(object sender, EventArgs e) {
            if(fEndpoint != null) {
                fEndpoint.Stop();
                fEndpoint = null;
            }
            btnStart.Enabled = true;
            btnStop.Enabled = false;
        }


        #region IPictureService Members

        public void Display(string fileName, Image picture) {
            if(InvokeRequired) {
                Action<String, Image> _callback = Display;
                Invoke(_callback, fileName, picture);
            }
            else {
                lblPictureName.Text = fileName;
                pictureBox1.Image = picture;
            }
        }

        #endregion
    }
}
